#include "AES.h"

const unsigned char code  Sbox[256] = {
    0x63,   0x7c,   0x77,   0x7b,   0xf2,   0x6b,   0x6f,   0xc5,   0x30,   0x01,   0x67,   0x2b,   0xfe,   0xd7,   0xab,   0x76,
    0xca,   0x82,   0xc9,   0x7d,   0xfa,   0x59,   0x47,   0xf0,   0xad,   0xd4,   0xa2,   0xaf,   0x9c,   0xa4,   0x72,   0xc0,
    0xb7,   0xfd,   0x93,   0x26,   0x36,   0x3f,   0xf7,   0xcc,   0x34,   0xa5,   0xe5,   0xf1,   0x71,   0xd8,   0x31,   0x15,
    0x04,   0xc7,   0x23,   0xc3,   0x18,   0x96,   0x05,   0x9a,   0x07,   0x12,   0x80,   0xe2,   0xeb,   0x27,   0xb2,   0x75,
    0x09,   0x83,   0x2c,   0x1a,   0x1b,   0x6e,   0x5a,   0xa0,   0x52,   0x3b,   0xd6,   0xb3,   0x29,   0xe3,   0x2f,   0x84,
    0x53,   0xd1,   0x00,   0xed,   0x20,   0xfc,   0xb1,   0x5b,   0x6a,   0xcb,   0xbe,   0x39,   0x4a,   0x4c,   0x58,   0xcf,
    0xd0,   0xef,   0xaa,   0xfb,   0x43,   0x4d,   0x33,   0x85,   0x45,   0xf9,   0x02,   0x7f,   0x50,   0x3c,   0x9f,   0xa8,
    0x51,   0xa3,   0x40,   0x8f,   0x92,   0x9d,   0x38,   0xf5,   0xbc,   0xb6,   0xda,   0x21,   0x10,   0xff,   0xf3,   0xd2,
    0xcd,   0x0c,   0x13,   0xec,   0x5f,   0x97,   0x44,   0x17,   0xc4,   0xa7,   0x7e,   0x3d,   0x64,   0x5d,   0x19,   0x73,
    0x60,   0x81,   0x4f,   0xdc,   0x22,   0x2a,   0x90,   0x88,   0x46,   0xee,   0xb8,   0x14,   0xde,   0x5e,   0x0b,   0xdb,
    0xe0,   0x32,   0x3a,   0x0a,   0x49,   0x06,   0x24,   0x5c,   0xc2,   0xd3,   0xac,   0x62,   0x91,   0x95,   0xe4,   0x79,
    0xe7,   0xc8,   0x37,   0x6d,   0x8d,   0xd5,   0x4e,   0xa9,   0x6c,   0x56,   0xf4,   0xea,   0x65,   0x7a,   0xae,   0x08,
    0xba,   0x78,   0x25,   0x2e,   0x1c,   0xa6,   0xb4,   0xc6,   0xe8,   0xdd,   0x74,   0x1f,   0x4b,   0xbd,   0x8b,   0x8a,
    0x70,   0x3e,   0xb5,   0x66,   0x48,   0x03,   0xf6,   0x0e,   0x61,   0x35,   0x57,   0xb9,   0x86,   0xc1,   0x1d,   0x9e,
    0xe1,   0xf8,   0x98,   0x11,   0x69,   0xd9,   0x8e,   0x94,   0x9b,   0x1e,   0x87,   0xe9,   0xce,   0x55,   0x28,   0xdf,
    0x8c,   0xa1,   0x89,   0x0d,   0xbf,   0xe6,   0x42,   0x68,   0x41,   0x99,   0x2d,   0x0f,   0xb0,   0x54,   0xbb,   0x16
};

const unsigned char code  SNbox[256] = {
    0x52,   0x09,   0x6a,   0xd5,   0x30,   0x36,   0xa5,   0x38,   0xbf,   0x40,   0xa3,   0x9e,   0x81,   0xf3,   0xd7,   0xfb,
    0x7c,   0xe3,   0x39,   0x82,   0x9b,   0x2f,   0xff,   0x87,   0x34,   0x8e,   0x43,   0x44,   0xc4,   0xde,   0xe9,   0xcb,
    0x54,   0x7b,   0x94,   0x32,   0xa6,   0xc2,   0x23,   0x3d,   0xee,   0x4c,   0x95,   0x0b,   0x42,   0xfa,   0xc3,   0x4e,
    0x08,   0x2e,   0xa1,   0x66,   0x28,   0xd9,   0x24,   0xb2,   0x76,   0x5b,   0xa2,   0x49,   0x6d,   0x8b,   0xd1,   0x25,
    0x72,   0xf8,   0xf6,   0x64,   0x86,   0x68,   0x98,   0x16,   0xd4,   0xa4,   0x5c,   0xcc,   0x5d,   0x65,   0xb6,   0x92,
    0x6c,   0x70,   0x48,   0x50,   0xfd,   0xed,   0xb9,   0xda,   0x5e,   0x15,   0x46,   0x57,   0xa7,   0x8d,   0x9d,   0x84,
    0x90,   0xd8,   0xab,   0x00,   0x8c,   0xbc,   0xd3,   0x0a,   0xf7,   0xe4,   0x58,   0x05,   0xb8,   0xb3,   0x45,   0x06,
    0xd0,   0x2c,   0x1e,   0x8f,   0xca,   0x3f,   0x0f,   0x02,   0xc1,   0xaf,   0xbd,   0x03,   0x01,   0x13,   0x8a,   0x6b,
    0x3a,   0x91,   0x11,   0x41,   0x4f,   0x67,   0xdc,   0xea,   0x97,   0xf2,   0xcf,   0xce,   0xf0,   0xb4,   0xe6,   0x73,
    0x96,   0xac,   0x74,   0x22,   0xe7,   0xad,   0x35,   0x85,   0xe2,   0xf9,   0x37,   0xe8,   0x1c,   0x75,   0xdf,   0x6e,
    0x47,   0xf1,   0x1a,   0x71,   0x1d,   0x29,   0xc5,   0x89,   0x6f,   0xb7,   0x62,   0x0e,   0xaa,   0x18,   0xbe,   0x1b,
    0xfc,   0x56,   0x3e,   0x4b,   0xc6,   0xd2,   0x79,   0x20,   0x9a,   0xdb,   0xc0,   0xfe,   0x78,   0xcd,   0x5a,   0xf4,
    0x1f,   0xdd,   0xa8,   0x33,   0x88,   0x07,   0xc7,   0x31,   0xb1,   0x12,   0x10,   0x59,   0x27,   0x80,   0xec,   0x5f,
    0x60,   0x51,   0x7f,   0xa9,   0x19,   0xb5,   0x4a,   0x0d,   0x2d,   0xe5,   0x7a,   0x9f,   0x93,   0xc9,   0x9c,   0xef,
    0xa0,   0xe0,   0x3b,   0x4d,   0xae,   0x2a,   0xf5,   0xb0,   0xc8,   0xeb,   0xbb,   0x3c,   0x83,   0x53,   0x99,   0x61,
    0x17,   0x2b,   0x04,   0x7e,   0xba,   0x77,   0xd6,   0x26,   0xe1,   0x69,   0x14,   0x63,   0x55,   0x21,   0x0c,   0x7d
};

const unsigned char code  Rcon[10] = {
    0x01,   0x02,   0x04,   0x08,   0x10,   0x20,   0x40,   0x80,   0x1B,   0x36
};

#define KEYEXP_BUF_SDRAM_ADDR_START_H     0x01
#define KEYEXP_BUF_SDRAM_ADDR_START_L     0x00

#define BUFFER_TMP_SDRAM_ADDR_START_H     0x01
#define BUFFER_TMP_SDRAM_ADDR_START_L     (KEYEXP_BUF_SDRAM_ADDR_START_L + 0x10)

#define SRC_DATA_SDRAM_ADDR_START_H       0x01
#define SRC_DATA_SDRAM_ADDR_START_L       (BUFFER_TMP_SDRAM_ADDR_START_L + 0x10)


static unsigned char xdata KeyExp_w[4][4] _at_ KEYEXP_BUF_SDRAM_ADDR_START_L ;// 轮秘钥计算完成后存储该轮轮秘钥


static unsigned char xdata buffer_tmp[4][4] _at_ BUFFER_TMP_SDRAM_ADDR_START_L ;
unsigned char xdata srcbuf[4][4] _at_ SRC_DATA_SDRAM_ADDR_START_L;


// void AES_SHIFT(unsigned char start_addrh,unsigned char start_addrl,unsigned char length,unsigned char type);
void AES_XOR(unsigned char src_addrh,unsigned char src_addrl,unsigned char add_addrh,unsigned char add_addrl,unsigned char length)
{
    unsigned char xdata *srcp;
    unsigned char xdata *addp;
    unsigned char xdata  i   ;
    unsigned char xdata  src_data;
    unsigned char xdata  add_data;
    srcp = (unsigned int) (src_addrl) ;
    addp = (unsigned int) (add_addrl) ;
    
    for(i=0;i<length;i++){
      src_data = *(srcp+i);
      add_data = *(addp+i);
      *(srcp+i) = src_data ^ add_data;
//      *(srcp+i) = *(srcp+i) ^ *(addp+i);
    }
}


unsigned char S_Transform( unsigned char inputdata)
{
    return Sbox[inputdata];
}
unsigned char SN_Transform( unsigned char inputdata)
{
    return SNbox[inputdata];
}

void AES_Init(void)
{
  unsigned char xdata i;
  for(i=0;i<16;i++){
    *(&srcbuf[0][0] + i) = 0;
  }
}

void AES_KeyRound(unsigned char step){

    unsigned char xdata i;

    //------------- i等于4的整倍数时 需要进行一次8bit移位且S盒变换
    // 1.将W3备份到W4,并移位：W[4][3]、W[3][2]、W[2][1]、W[1][0]  ->   W[4][2]、W[4][1]、W[4][0]、W[4][3]
    buffer_tmp[0][3] = KeyExp_w[3][0];
    buffer_tmp[0][0] = KeyExp_w[3][1];
    buffer_tmp[0][1] = KeyExp_w[3][2];
    buffer_tmp[0][2] = KeyExp_w[3][3];

    // 2.分别将W[4]放入S盒进行变换
    buffer_tmp[0][0] = Sbox[buffer_tmp[0][0]];
    buffer_tmp[0][1] = Sbox[buffer_tmp[0][1]];
    buffer_tmp[0][2] = Sbox[buffer_tmp[0][2]];
    buffer_tmp[0][3] = Sbox[buffer_tmp[0][3]];

    // 3.将w[4]与轮常量Rcon进行异或
    buffer_tmp[0][0] = buffer_tmp[0][0] ^ Rcon[step];
  
    // 4.将W[4]与w[0]的异或值写入w[0]
    AES_XOR(KEYEXP_BUF_SDRAM_ADDR_START_H,KEYEXP_BUF_SDRAM_ADDR_START_L,KEYEXP_BUF_SDRAM_ADDR_START_H,BUFFER_TMP_SDRAM_ADDR_START_L,4);

    //------------- 计算 W[i] 的值
    for(i = 1 ; i < 4 ;i++) {
        // 5.将w[i]与W[i-1]相异或,新的值存在W[i]内
        AES_XOR(KEYEXP_BUF_SDRAM_ADDR_START_H,KEYEXP_BUF_SDRAM_ADDR_START_L+(i<<2),KEYEXP_BUF_SDRAM_ADDR_START_H,KEYEXP_BUF_SDRAM_ADDR_START_L+(i-1)<<2,4);
    }
    // 执行结束后，W3 W2 W1 W0 中放的就是轮秘钥
}


///////////////////////////////////////////////////////////////
//功能: 伽罗瓦域内的乘法运算 GF(128)
//参数: Num_L 输入的左参数
// Num_R 输入的右参数
//返回值:计算结果
unsigned char AES_LineMul(unsigned char Num_R,unsigned char Num_L)
{
  //定义变量
  unsigned char xdata Result = 0; //伽罗瓦域内乘法计算的结果

  while (Num_L)
  {
    //如果Num_L最低位是1就异或Num_R，相当于加上Num_R * 1
    if (Num_L & 0x01)  {
      Result ^= Num_R;
    }

    //Num_L右移一位，相当于除以2
    Num_L = Num_L >> 1;

    //如果Num_R最高位为1
    if (Num_R & 0x80){
      //左移一位相当于乘二
      Num_R = Num_R << 1; //注：这里会丢失最高位，但是不用担心

      Num_R ^= 0x1B; //计算伽罗瓦域内除法Num_R = Num_R / (x^8(刚好丢失最高位) + x^4 + x^3 + x^1 + 1)
    }
    else  {
      //左移一位相当于乘二
      Num_R = Num_R << 1;
    }
  }
  return Result;
}
const unsigned char code MixArray[4][4] =
{
0x02, 0x03, 0x01, 0x01,
0x01, 0x02, 0x03, 0x01,
0x01, 0x01, 0x02, 0x03,
0x03, 0x01, 0x01, 0x02
};
const unsigned char code NMixArray[4][4] =
{
0x0E, 0x0B, 0x0D, 0x09,
0x09, 0x0E, 0x0B, 0x0D,
0x0D, 0x09, 0x0E, 0x0B,
0x0B, 0x0D, 0x09, 0x0E
};
// 加密算法流程
unsigned char* AES_Encryption(unsigned char* sdata_start_addr,unsigned char* key_start_addr,unsigned char block_max)
{
    unsigned char xdata i,j;
    unsigned char xdata block_cnt,round_cnt;

    for(block_cnt = 0; block_cnt < block_max ; block_cnt++){

        // 1. 明文填充，默认大端存储
        for(i = 0 ; i < 16 ;i++){
            // CBC模式，和上一个block值进行异或
            *((&srcbuf[0][0]) + i) = (*(sdata_start_addr +(block_cnt<<4)+ i)) ^ *((&srcbuf[0][0]) + i);
        }

        // 2. 秘钥填充
        for(i = 0 ; i < 16 ;i++){
            *((&KeyExp_w[0][0]) + i) = *(key_start_addr + i);
        }

        // 3.轮秘钥加
        AES_XOR(SRC_DATA_SDRAM_ADDR_START_H,SRC_DATA_SDRAM_ADDR_START_L,KEYEXP_BUF_SDRAM_ADDR_START_H,KEYEXP_BUF_SDRAM_ADDR_START_L,16);

        // 4.执行10次轮函数
        for(round_cnt = 0 ; round_cnt < 10 ; round_cnt++) {

            // 4.1 获取该轮轮秘钥
            AES_KeyRound(round_cnt);
          
            // 4.2 S盒变换
            for(i = 0 ; i < 16 ; i++){
              *((&srcbuf[0][0]) + i) = Sbox[*((&srcbuf[0][0]) + i)];
            }

            // 4.3 行移位操作 可优化项
            buffer_tmp[0][3] = srcbuf[0][1]; srcbuf[0][1] = srcbuf[1][1] ; srcbuf[1][1] = srcbuf[2][1]       ; srcbuf[2][1]    = srcbuf[3][1]    ;srcbuf[3][1] = buffer_tmp[0][3];
            buffer_tmp[0][3] = srcbuf[3][3]; srcbuf[3][3] = srcbuf[2][3] ; srcbuf[2][3] = srcbuf[1][3]       ; srcbuf[1][3]    = srcbuf[0][3]    ;srcbuf[0][3] = buffer_tmp[0][3];
            buffer_tmp[0][3] = srcbuf[0][2]; srcbuf[0][2] = srcbuf[2][2] ; srcbuf[2][2] = buffer_tmp[0][3]   ;buffer_tmp[0][3] = srcbuf[1][2]    ;srcbuf[1][2] = srcbuf[3][2]    ; srcbuf[3][2] = buffer_tmp[0][3];

            if(round_cnt != 9) {
              // 4.4 列混合操作
              for(i = 0; i < 4 ;i++){
                  for(j = 0 ; j < 4 ;j++){
                    buffer_tmp[j][i] =
                    AES_LineMul(srcbuf[j][0],MixArray[i][0] ) ^
                    AES_LineMul(srcbuf[j][1],MixArray[i][1] ) ^
                    AES_LineMul(srcbuf[j][2],MixArray[i][2] ) ^
                    AES_LineMul(srcbuf[j][3],MixArray[i][3] );
                  }
              }
              // 4.6.输出轮密文 -- 可优化
              for(i = 0 ; i < 4 ;i++){
                for(j=0;j<4;j++)
                  srcbuf[i][j] = buffer_tmp[i][j];
              }
            }

            // 4.5轮秘钥加
            AES_XOR(SRC_DATA_SDRAM_ADDR_START_H,SRC_DATA_SDRAM_ADDR_START_L,KEYEXP_BUF_SDRAM_ADDR_START_H,KEYEXP_BUF_SDRAM_ADDR_START_L,16);
        }
    }
    return &srcbuf[0][0];
}

// 解密算法流程
unsigned char* AES_Decryption(unsigned char* sdata_start_addr,unsigned char* key_start_addr,unsigned char block_max)
{
    unsigned char xdata i,j;
    unsigned char xdata block_cnt,round_cnt;

    for(block_cnt = block_max; block_cnt > 0 ; block_cnt --){

        // 1. 密文填充，默认大端存储
        for(i = 0 ; i < 16 ;i++){
            *((&srcbuf[0][0]) + i) = *(sdata_start_addr + ((block_cnt-1)<<4) + i);
        }

        // 2. 秘钥填充
        for(i = 0 ; i < 16 ;i++){
            *((&KeyExp_w[0][0]) + i) = *(key_start_addr + i);
        }
        for(i=0;i<10;i++)   AES_KeyRound(i);

        // 3.轮秘钥加
        AES_XOR(SRC_DATA_SDRAM_ADDR_START_H,SRC_DATA_SDRAM_ADDR_START_L,KEYEXP_BUF_SDRAM_ADDR_START_H,KEYEXP_BUF_SDRAM_ADDR_START_L,16);

        // 4.执行10次轮函数
        for(round_cnt = 10 ; round_cnt > 0 ; round_cnt--) {

            

          // 4.1 逆行移位操作 可优化项--需要重点检查！！检查完修改注释
          buffer_tmp[0][3] = srcbuf[3][1];srcbuf[3][1] = srcbuf[2][1];srcbuf[2][1] = srcbuf[1][1];srcbuf[1][1] = srcbuf[0][1];srcbuf[0][1] = buffer_tmp[0][3]; 
          buffer_tmp[0][3] = srcbuf[0][3];srcbuf[0][3] = srcbuf[1][3];srcbuf[1][3] = srcbuf[2][3];srcbuf[2][3] = srcbuf[3][3];srcbuf[3][3] = buffer_tmp[0][3];

          buffer_tmp[0][3] = srcbuf[0][2];srcbuf[0][2] = srcbuf[2][2];srcbuf[2][2] = buffer_tmp[0][3];
          buffer_tmp[0][3] = srcbuf[1][2];srcbuf[1][2] = srcbuf[3][2];srcbuf[3][2] = buffer_tmp[0][3] ;
          
          

            // 4.2 逆盒变换
            for(i=0;i<16;i++){           *(&(srcbuf[0][0])+i) = SN_Transform(*(&(srcbuf[0][0])+i));            }
            
            // 4.3 获取该轮轮秘钥
            for(i = 0 ; i < 16 ;i++){    *((&KeyExp_w[0][0]) + i) = *(key_start_addr + i);            }
            if(round_cnt!=1) for(i=0;i<(round_cnt-1);i++)   
              AES_KeyRound(i);
            
            // 4.4 轮秘钥加
            AES_XOR(SRC_DATA_SDRAM_ADDR_START_H,SRC_DATA_SDRAM_ADDR_START_L,KEYEXP_BUF_SDRAM_ADDR_START_H,KEYEXP_BUF_SDRAM_ADDR_START_L,16);
            
            
            // 4.5 逆列混合操作
            if(round_cnt != 1) {       // 最后一个周期不执行列混合
              for(i = 0; i < 4 ;i++){

                  for(j = 0 ; j < 4 ;j++){
                      for(j = 0 ; j < 4 ;j++){
                      buffer_tmp[j][i] =
                      AES_LineMul(srcbuf[j][0],NMixArray[i][0] ) ^
                      AES_LineMul(srcbuf[j][1],NMixArray[i][1] ) ^
                      AES_LineMul(srcbuf[j][2],NMixArray[i][2] ) ^
                      AES_LineMul(srcbuf[j][3],NMixArray[i][3] ) ;
                    }
                  }
              }
              
              // 4.6 输出轮明文
              for(i = 0 ; i < 16 ;i++){
                  *((&srcbuf[0][0]) + i) = *((&buffer_tmp[0][0]) + i) ;
              }
            }
            
        }

    }
    return &srcbuf[0][0];
}